package com.suduku.calc;

import com.suduku.entity.Box;

import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * 单宫行列法 <br/>
 * 测试数据：DataConstant.XING_02_10
 */
public class GridXYCalc extends AbstractCalc {

    @Override
    Box solve() {
        Set<Map.Entry<Integer, List<Box>>> entries = getGMap().entrySet();
        // 遍历所有宫
        for(Map.Entry<Integer, List<Box>> entry : entries) {
            // 遍历所有候选数字
            for(Integer n : Box.INIT_LIST) {
                // 获取当前宫中候选数字为n的单元格列表
                List<Box> nList = entry.getValue().stream().filter(b -> b.isBlank() && b.getCList().contains(n)).collect(Collectors.toList());
                // 如果存在候选数字n的空白格
                if(!nList.isEmpty()) {
                    // 获取这些单元格的横坐标，判断是否在同一行中
                    Set<Integer> xSet = nList.stream().map(Box::getX).collect(Collectors.toSet());
                    if(xSet.size() == 1) {
                        // 获取该行中，非当前宫的单元格，如果候选数字中存在n，则剔除
                        Integer x = xSet.iterator().next();
                        List<Box> oxList = getXList(x).stream().filter(b -> b.isBlank() && b.getG() != entry.getKey() && b.getCList().contains(n)).collect(Collectors.toList());
                        for(Box box : oxList) {
                            change(box, nList, n);
                            box.removeCList(n);
                            return box;
                        }
                    }
                    // 获取这些单元格的纵坐标，判断是否在同一列中
                    Set<Integer> ySet = nList.stream().map(Box::getY).collect(Collectors.toSet());
                    if(ySet.size() == 1) {
                        // 获取该列中，非当前宫的单元格，如果候选数字中存在n，则剔除
                        Integer y = ySet.iterator().next();
                        List<Box> oyList = getYList(y).stream().filter(b -> b.isBlank() && b.getG() != entry.getKey() && b.getCList().contains(n)).collect(Collectors.toList());
                        for(Box box : oyList) {
                            change(box, nList, n);
                            box.removeCList(n);
                            return box;
                        }
                    }
                }
            }
        }
        return null;
    }

}
